package bot;

import extmodule.IF_ExtModule_Feed;
import extmodule.IF_ExtModule_GetProposal;
import game.Player;
import game.model.Card;
import bot.module.equity.*;
import bot.module.th.shc.*;

import java.io.*;

import util.DebugOut;
import util.poker.texas.BetInt;
import static util.poker.texas.BetInt.*;

/**
 * An example bot which implements its strategy in java.
 * @author Witthold/Korol
 */
public class HSBremen1 extends Bot {

	/**
	 * Creates a new instance of HSBremen1
	 * @param config - bots configuration file, "default.config" if nothing is passed
	 * @throws FileNotFoundException
	 */
	public HSBremen1(String config) {
		super(config);
	}


	public static void main(String[] args) throws Exception {
		String config = "estimation.config";
		try {
			if (args != null) {
				if (args.length > 0) {
					DebugOut.showVerboseMain(args[0]);
					config = args[0] + ".config";
				}
			}
		} finally {
			Bot bot = new HSBremen1(config);
			bot.run();
		}
	}

	@Override
	protected boolean isPlayable() {

		// TODO implement this function to check if the bot can/want play this kind of game
		return true;
	}

	@Override
	public int[] getBet() {

		int numActives = state.getActivePlayers().length;
		int[] proposal = new int[2];

		Player self = state.getPlayers()[0];

		if (!extFeeds.isEmpty() && extFeeds.get(0) instanceof IF_ExtModule_GetProposal) {

			for (IF_ExtModule_Feed feed : extFeeds) {

				if (feed instanceof IF_ExtModule_GetProposal) {
					proposal[0] = ((IF_ExtModule_GetProposal) feed).getProposal(); // TODO this proposal will be overwritten
					break;
				}
			}
		}
		
		/* Module StartingHandChart */
		if (!proposals.isEmpty() && proposals.get(0) instanceof IF_StartingHandChart && state.getCurrentRound() == 0) {

			if (state.getRound(0).getHistory(0).size() == 0
					|| state.getRound(0).getHistory(0).size() == 1 
					&& state.getRound(0).getHistory(0).get(0).isBlind()) { /* first voluntary action */

				proposal = ((StartingHandChart) proposals.get(0)).getProposal(self.getHoleCards(), numActives, state.getSmallBlind(), state.getBigBlind(),
						self.getCurrentPosition(), state.getRound().getCalls(), state.getRound().getRaises());

				DebugOut.showVerboseBot("handleStateChange - get proposal by shc: " + proposal[0] + ", " + proposal[1]);

			} else { /* it is not the first action */

				if (!equities.isEmpty() && equities.get(0) instanceof IF_Equity) {

					int potSize = state.getPotSize();
					int callSize = state.getHighestBet() - self.getCurrentBet();
					// TODO if call size 0 -> check or raise (dependent on numActives and potSize? but not on odds)  

					Card[][] holeCards = new Card[numActives][];
					Card[] boardCards = state.getBoardCards();
					Card[] deadCards = state.getDeadCards();

					for (int i = 0; i < holeCards.length; i++) {

						holeCards[i] = state.getActivePlayers()[i].getHoleCards();
					}

					double[] saie = ((SubjectiveAllinEquity) equities.get(0)).getEquity(1000, 1000, holeCards, boardCards, deadCards);

					if (saie[0] * potSize >= callSize) {

						DebugOut.showVerbosePotEquity("good odds!");
						proposal[0] = CALL;

					} else {

						DebugOut.showVerbosePotEquity("bad odds!");
						proposal[0] = FOLD;
					}

				} else { /* equities == null */

					proposal = getRandomBet();
				}
			}

		} else { /* not the first round or no starting hand chart */
			
			/* Module SubjectiveAllinEquity */
			if (!equities.isEmpty() && equities.get(0) instanceof IF_Equity) {

				int potSize = state.getPotSize();
				int callSize = state.getHighestBet() - self.getCurrentBet();

				Card[][] holeCards = new Card[numActives][];
				Card[] boardCards = state.getBoardCards();
				Card[] deadCards = state.getDeadCards();

				for (int i = 0; i < holeCards.length; i++) {

					holeCards[i] = state.getActivePlayers()[i].getHoleCards();
				}

				double[] saie = ((SubjectiveAllinEquity) equities.get(0)).getEquity(1000, 1000, holeCards, boardCards, deadCards);	
				// TODO calculate the amount of samples instead of simply use 1000 

				if (saie[0] * potSize >= callSize) {

					if(saie[0] * potSize >= 4*callSize)
						proposal[0] = RAISE;
					else
						proposal[0] = CALL;

					DebugOut.showVerbosePotEquity("good odds!");

				} else {

					DebugOut.showVerbosePotEquity("bad odds!");
					proposal[0] = FOLD;
				}

			} else { /* equities == null */

				proposal = getRandomBet();
			}

		}
		return proposal;
	}
}